/*
 * Common usable utilities
 *
 * Copyright (c) 2006
 *   Petr Hadraba <hadrabap@bluetone.cz>
 *
 * Author: Petr Hadraba
 *
 * --
 *
 * XML Utilities
 */

package global.sandbox.xmlutilities;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.Map;
import javax.xml.namespace.NamespaceContext;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.SchemaFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathFactoryConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * Static version of the XMLUtilities class.
 * 
 * @author Petr Hadraba
 * 
 * @version 1.1
 */
public abstract class XMLTools {
    
    /**
     * Use this constant, if you want to use internal XMLUtilities for the
     * static methods
     */
    private static final XMLUtilities INTERNAL_XMLUTILITIES = null;
    
    /**
     * stores XMLUtilities object for the static usage
     */
    private static XMLUtilities xmlUtilities = null;
    
    /**
     * hidden constructor
     */
    protected XMLTools() {
        super();
    }
    
    /**
     * converts Document to DOMSource object
     * 
     * @param source
     *            Document XML representation
     * 
     * @return converted XML source
     */
    public static Source documentToDOMSource(final Document source) {
        return new DOMSource(source);
    }
    
    /**
     * converts Document to DOMSource object
     * 
     * @param source
     *            Document XML representation
     * @param systemId
     *            system ID
     * 
     * @return converted XML source
     */
    public static Source documentToDOMSource(final Document source,
            String systemId) {
        return new DOMSource(source, systemId);
    }
    
    /**
     * converst XML Document into String
     * 
     * @param source
     *            Document to convert
     * @param xmlUtilities
     *            custom XMLUtilities; can be null
     * 
     * @return XML in the String
     * 
     * @throws TransformerException
     * @throws IOException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static String documentToString(final Document source,
            final XMLUtilities xmlUtilities) throws TransformerException,
            IOException, XPathFactoryConfigurationException,
            ParserConfigurationException {
        if (xmlUtilities != null) {
            return xmlUtilities.documentToString(source);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.documentToString(source);
    }
    
    /**
     * converst XML Document into String
     * 
     * @param source
     *            Document to convert
     * 
     * @return XML in the String
     * 
     * @throws TransformerException
     * @throws IOException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static String documentToString(final Document source)
            throws TransformerException, IOException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        return documentToString(source, INTERNAL_XMLUTILITIES);
    }
    
    /**
     * evaluates specified XPath expression on specified context node
     * 
     * @param query
     *            XPath expression
     * @param context
     *            context node
     * @param namespaces
     *            namespace context
     * @param xmlUtilities
     *            custom XMLUtilities; can be null
     * 
     * @return NodeList or null if no matches
     * 
     * @throws XPathExpressionException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static NodeList evaluateXPath(final String query,
            final Node context, final NamespaceContext namespaces,
            final XMLUtilities xmlUtilities) throws XPathExpressionException,
            TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        if (xmlUtilities != null) {
            return xmlUtilities.evaluateXPath(query, context, namespaces);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.evaluateXPath(query, context, namespaces);
    }
    
    /**
     * evaluates specified XPath expression on specified context node
     * 
     * @param query
     *            XPath expression
     * @param context
     *            context node
     * @param namespaces
     *            namespace context
     * 
     * @return NodeList or null if no matches
     * 
     * @throws XPathExpressionException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static NodeList evaluateXPath(final String query, final Node context,
            final NamespaceContext namespaces) throws XPathExpressionException,
            TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        return evaluateXPath(query, context, namespaces, INTERNAL_XMLUTILITIES);
    }
    
    /**
     * evaluates specified XPath expression on specified context node
     * 
     * @param query
     *            XPath expression
     * @param context
     *            context node
     * @param xmlUtilities
     *            custom XMLUtilities; can be null
     * 
     * @return NodeList or null if no matches
     * 
     * @throws XPathExpressionException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static NodeList evaluateXPath(final String query,
            final Node context, final XMLUtilities xmlUtilities)
            throws XPathExpressionException, TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        if (xmlUtilities != null) {
            return xmlUtilities.evaluateXPath(query, context);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.evaluateXPath(query, context);
    }
    
    /**
     * evaluates specified XPath expression on specified context node
     * 
     * @param query
     *            XPath expression
     * @param context
     *            context node
     * 
     * @return NodeList or null if no matches
     * 
     * @throws XPathExpressionException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static NodeList evaluateXPath(final String query, final Node context)
            throws XPathExpressionException, TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        return evaluateXPath(query, context, INTERNAL_XMLUTILITIES);
    }
    
    /**
     * evaluates specified XPath expression and returnes first Node if XPath has
     * matches
     * 
     * @param query
     *            XPath expression
     * @param context
     *            context node
     * @param xmlUtilities
     *            xustom XMLUtilities; can be null
     * 
     * @return first node or null
     * 
     * @throws XPathExpressionException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static Node getFirstNodeForXPath(final String query,
            final Node context, final XMLUtilities xmlUtilities)
            throws XPathExpressionException, TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        if (xmlUtilities != null) {
            return xmlUtilities.getFirstNodeForXPath(query, context);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.getFirstNodeForXPath(query, context);
    }
    
    /**
     * evaluates specified XPath expression and returnes first Node if XPath has
     * matches
     * 
     * @param query
     *            XPath expression
     * @param context
     *            context node
     * 
     * @return first node or null
     * 
     * @throws XPathExpressionException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static Node getFirstNodeForXPath(final String query,
            final Node context) throws XPathExpressionException,
            TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        return getFirstNodeForXPath(query, context, INTERNAL_XMLUTILITIES);
    }
    
    /**
     * evaluates specified XPath expression and returnes first Node if XPath has
     * matches
     * 
     * @param query
     *            XPath expression
     * @param context
     *            context node
     * @param namespaces
     *            namespace context
     * @param xmlUtilities
     *            xustom XMLUtilities; can be null
     * 
     * @return first node or null
     * 
     * @throws XPathExpressionException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static Node getFirstNodeForXPath(final String query,
            final Node context, final NamespaceContext namespaces,
            final XMLUtilities xmlUtilities) throws XPathExpressionException,
            TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        if (xmlUtilities != null) {
            return xmlUtilities.getFirstNodeForXPath(
                    query, context, namespaces);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.getFirstNodeForXPath(
                query, context, namespaces);
    }
    
    /**
     * evaluates specified XPath expression and returnes first Node if XPath has
     * matches
     * 
     * @param query
     *            XPath expression
     * @param context
     *            context node
     * @param namespaces
     *            namespace context
     * @return first node or null
     * 
     * @throws XPathExpressionException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static Node getFirstNodeForXPath(final String query,
            final Node context, final NamespaceContext namespaces)
            throws XPathExpressionException,
            TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        return getFirstNodeForXPath(
                query, context, namespaces, INTERNAL_XMLUTILITIES);
    }
    
    /**
     * initializes XMLUtilities static member for the static usage
     * 
     * @throws ParserConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws TransformerConfigurationException
     */
    private static void initializeXMLUtilities()
            throws TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        XMLTools.xmlUtilities = new XMLUtilities();
    }
    
    /**
     * initializes XMLUtilities static member for the static usage using
     * specified XMLUtilities
     * 
     * @param xmlUtilities
     *            XMLUtilities to use
     */
    public static void initializeXMLUtilities(final XMLUtilities xmlUtilities) {
        if (xmlUtilities == null) {
            throw new NullPointerException();
        }
        
        XMLTools.xmlUtilities = xmlUtilities;
    }
    
    /**
     * obtains SchemaFactory object internaly used by the XMLUtilities static
     * methods
     * 
     * @return SchemaFactory object
     */
    public static SchemaFactory getInternalSchemaFactory() {
        if (xmlUtilities == null) {
            return null;
        }
        
        return xmlUtilities.getSchemaFactory();
    }
    
    /**
     * obtains DocumentBuilder object internaly used by the XMLUtilities static
     * methods
     * 
     * @return DocumentBuilder object
     */
    public static DocumentBuilder getInternalDocumentBuilder() {
        if (xmlUtilities == null) {
            return null;
        }
        
        return xmlUtilities.getDocumentBuilder();
    }
    
    /**
     * obtains TransformerFactory object internaly used by the XMLUtilities
     * static methods
     * 
     * @return TransformerFactory object
     */
    public static TransformerFactory getInternalTransformerFactory() {
        if (xmlUtilities == null) {
            return null;
        }
        
        return xmlUtilities.getTransformerFactory();
    }
    
    /**
     * obtains Transformer object internaly used by the XMLUtilities static
     * methods
     * 
     * @return Transformer object
     */
    public static Transformer getInternalTransformer() {
        if (xmlUtilities == null) {
            return null;
        }
        
        return xmlUtilities.getTransformer();
    }
    
    /**
     * obtains XPathFactory object internaly used by the XMLUtilities static
     * methods
     * 
     * @return XPathFactory object
     */
    public static XPathFactory getInternalXPathFactory() {
        if (xmlUtilities == null) {
            return null;
        }
        
        return xmlUtilities.getXPathFactory();
    }
    
    /**
     * obtains NamespaceContext object internaly used by the XMLUtilities static
     * methods
     *
     * @return NamespaceContext object
     */
    public static NamespaceContext getInternalNamespaceContext() {
        if (xmlUtilities == null) {
            return null;
        }
        
        return xmlUtilities.getDefaultNamespaceContext();
    }
    
    /**
     * validates specified XML with the specified XMLScheme
     * 
     * @param xmlDocument
     *            XML document to validate
     * @param xmlSchema
     *            XMLSchema
     * @param xmlUtilities
     *            specified XMLUtilities. if null, internal will be used
     * 
     * @return null if successfull, string with error otherwise
     * 
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws IOException
     */
    public static String validateXmlUsingSchema(final Source xmlDocument,
            final Source xmlSchema, final XMLUtilities xmlUtilities)
            throws TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException,
            IOException {
        if (xmlUtilities != null) {
            return xmlUtilities.validateXmlUsingSchema(xmlDocument, xmlSchema);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.validateXmlUsingSchema(xmlDocument,
                xmlSchema);
    }
    
    /**
     * validates specified XML with the specified XMLScheme
     * 
     * @param xmlDocument
     *            XML document to validate
     * @param xmlSchema
     *            XMLSchema
     * 
     * @return null if successfull, string with error otherwise
     * 
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws IOException
     */
    public static String validateXmlUsingSchema(final Source xmlDocument,
            final Source xmlSchema) throws TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException,
            IOException {
        return validateXmlUsingSchema(xmlDocument, xmlSchema,
                INTERNAL_XMLUTILITIES);
    }
    
    /**
     * loads XML from file specified with file name
     * 
     * @param fileName
     *            file to load
     * @param xmlUtilities
     *            custom XMLUtilities object; can be null
     * 
     * @return Document object
     * 
     * @throws FileNotFoundException
     * @throws IOException
     * @throws SAXException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static Document loadDocumentFromFile(final String fileName,
            final XMLUtilities xmlUtilities) throws FileNotFoundException,
            IOException, SAXException, TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        if (xmlUtilities != null) {
            return xmlUtilities.loadDocumentFromFile(fileName);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.loadDocumentFromFile(fileName);
    }
    
    /**
     * loads XML from file specified with file name
     * 
     * @param fileName
     *            file to load
     * 
     * @return Document object
     * 
     * @throws FileNotFoundException
     * @throws IOException
     * @throws SAXException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static Document loadDocumentFromFile(final String fileName)
            throws FileNotFoundException, IOException, SAXException,
            TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        return loadDocumentFromFile(fileName, INTERNAL_XMLUTILITIES);
    }
    
    /**
     * loads XML from file specified with file name
     * 
     * @param fileName
     *            file to load
     * @param documentBuilder
     *            custom DocumentBuilder
     * @param xmlUtilities
     *            custom XMLUtilities; can be null
     * 
     * @return Document object
     * 
     * @throws FileNotFoundException
     * @throws IOException
     * @throws SAXException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static Document loadDocumentFromFile(final String fileName,
            final DocumentBuilder documentBuilder,
            final XMLUtilities xmlUtilities) throws FileNotFoundException,
            IOException, SAXException, TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        if (xmlUtilities != null) {
            return xmlUtilities.loadDocumentFromFile(fileName, documentBuilder);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.loadDocumentFromFile(fileName,
                documentBuilder);
    }
    
    /**
     * loads XML from file specified with file name
     * 
     * @param fileName
     *            file to load
     * @param documentBuilder
     *            custom DocumentBuilder
     * 
     * @return Document object
     * 
     * @throws FileNotFoundException
     * @throws IOException
     * @throws SAXException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static Document loadDocumentFromFile(final String fileName,
            final DocumentBuilder documentBuilder)
            throws FileNotFoundException, IOException, SAXException,
            TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        return loadDocumentFromFile(fileName, documentBuilder,
                INTERNAL_XMLUTILITIES);
    }
    
    /**
     * loads XML from file specified with the File object
     * 
     * @param file
     *            file to load
     * @param xmlUtilities
     *            custom XMLUtilities; can be null
     * 
     * @return Document object
     * 
     * @throws FileNotFoundException
     * @throws IOException
     * @throws SAXException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static Document loadDocumentFromFile(final File file,
            final XMLUtilities xmlUtilities) throws FileNotFoundException,
            IOException, SAXException, TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        if (xmlUtilities != null) {
            return xmlUtilities.loadDocumentFromFile(file);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.loadDocumentFromFile(file);
    }
    
    /**
     * loads XML from file specified with the File object
     * 
     * @param file
     *            file to load
     * 
     * @return Document object
     * 
     * @throws FileNotFoundException
     * @throws IOException
     * @throws SAXException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static Document loadDocumentFromFile(final File file)
            throws FileNotFoundException, IOException, SAXException,
            TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        return loadDocumentFromFile(file, INTERNAL_XMLUTILITIES);
    }
    
    /**
     * loads XML from file specified with the file object
     * 
     * @param file
     *            fileto load
     * @param documentBuilder
     *            custom document builder
     * @param xmlUtilities
     *            custom XMLUtilities; can be null
     * 
     * @return Document object
     * 
     * @throws FileNotFoundException
     * @throws IOException
     * @throws SAXException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static Document loadDocumentFromFile(final File file,
            final DocumentBuilder documentBuilder,
            final XMLUtilities xmlUtilities) throws FileNotFoundException,
            IOException, SAXException, TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        if (xmlUtilities != null) {
            return xmlUtilities.loadDocumentFromFile(file, documentBuilder);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities
                .loadDocumentFromFile(file, documentBuilder);
    }
    
    /**
     * loads XML from file specified with the file object
     * 
     * @param file
     *            fileto load
     * @param documentBuilder
     *            custom document builder
     * 
     * @return Document object
     * 
     * @throws FileNotFoundException
     * @throws IOException
     * @throws SAXException
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     */
    public static Document loadDocumentFromFile(final File file,
            final DocumentBuilder documentBuilder)
            throws FileNotFoundException, IOException, SAXException,
            TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException {
        return loadDocumentFromFile(file, documentBuilder,
                INTERNAL_XMLUTILITIES);
    }
    
    /**
     * loads XML from specified stream
     * 
     * @param is
     *            input stream
     * @param xmlUtilities
     *            custom XMLUtilities (can be null)
     * 
     * @return Document object
     * 
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws SAXException
     */
    public static Document loadDocumentFromStream(final InputStream is,
            final XMLUtilities xmlUtilities)
            throws TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException,
            IOException, SAXException {
        if (xmlUtilities != null) {
            return xmlUtilities.loadDocumentFromStream(is);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.loadDocumentFromStream(is);
    }
    
    /**
     * loads XML from specified stream
     * 
     * @param is
     *            input stream
     * 
     * @return Document object
     * 
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws SAXException
     */
    public static Document loadDocumentFromStream(final InputStream is)
            throws TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException,
            IOException, SAXException {
        return loadDocumentFromStream(is, INTERNAL_XMLUTILITIES);
    }
    
    /**
     * loads XML from specified input stream
     * 
     * @param is
     *            input stream
     * @param documentBuilder
     *            custom Document Builder
     * @param xmlUtilities
     *            custom XMLUtilities (can be null)
     * 
     * @return Document object
     * 
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws SAXException
     */
    public static Document loadDocumentFromStream(final InputStream is,
            final DocumentBuilder documentBuilder,
            final XMLUtilities xmlUtilities)
            throws TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException,
            IOException, SAXException {
        if (xmlUtilities != null) {
            return xmlUtilities.loadDocumentFromStream(is, documentBuilder);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities
                .loadDocumentFromStream(is, documentBuilder);
    }
    
    /**
     * loads XML from specified input stream
     * 
     * @param is
     *            input stream
     * @param documentBuilder
     *            custom Document Builder
     * 
     * @return Document object
     * 
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws SAXException
     */
    public static Document loadDocumentFromStream(final InputStream is,
            final DocumentBuilder documentBuilder)
            throws TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException,
            IOException, SAXException {
        return loadDocumentFromStream(is, documentBuilder,
                INTERNAL_XMLUTILITIES);
    }
    
    /**
     * obtains DocumentBuilderFactory object internaly used by the XMLUtilities
     * static methods
     * 
     * @return DocumentBuilderFactory object
     */
    public static DocumentBuilderFactory getInternalDocumentBuilderFactory() {
        if (xmlUtilities == null) {
            return null;
        }
        
        return xmlUtilities.getDocumentBuilderFactory();
    }
    
    /**
     * obtains XPath object internaly used by the XMLUtilities static methods
     * 
     * @return XPath object
     */
    public static XPath getInternalXPath() {
        if (xmlUtilities == null) {
            return null;
        }
        
        return xmlUtilities.getXPath();
    }
    
    /**
     * transformes specified XML document using specified XSLT template
     * 
     * @param xsltTemplate
     *            template to use
     * @param document
     *            source XML document
     * 
     * @return resulting document in the <code>String</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws TransformerException
     */
    public static String transformToString(final Source xsltTemplate,
            final Source document) throws XPathFactoryConfigurationException,
            ParserConfigurationException, TransformerException {
        return transformToString(xsltTemplate, document,
                XMLTools.INTERNAL_XMLUTILITIES);
    }
    
    /**
     * transformes specified XML document using specified XSLT template
     * 
     * @param xsltTemplate
     *            XSLT template
     * @param document
     *            source XML document
     * @param xmlUtilities
     *            custom <code>XMLUtilities</code>
     * 
     * @return resulting XML document in the <code>String</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws TransformerException
     */
    public static String transformToString(final Source xsltTemplate,
            final Source document, final XMLUtilities xmlUtilities)
            throws XPathFactoryConfigurationException,
            ParserConfigurationException, TransformerException {
        return transformToString(xsltTemplate, document, null, xmlUtilities);
    }
    
    /**
     * transformes specified XML document using specified XSLT template
     * 
     * @param xsltTemplate
     *            XSLT template to use
     * @param document
     *            source XML document
     * @param parameters
     *            parameters for the XSLT processor
     * 
     * @return resulting XML file in the <code>String</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws TransformerException
     */
    public static String transformToString(final Source xsltTemplate,
            final Source document, final Map<String, Object> parameters)
            throws XPathFactoryConfigurationException,
            ParserConfigurationException, TransformerException {
        return transformToString(xsltTemplate, document, parameters,
                XMLTools.INTERNAL_XMLUTILITIES);
    }
    
    /**
     * transformes specified XML document using specified XSLT template
     * 
     * @param xsltTemplate
     *            XSLT template to use
     * @param document
     *            source XML document
     * @param parameters
     *            parameters for the XSLT processor
     * @param xmlUtilities
     *            custom <code>XMLUtilities</code> to use
     * 
     * @return resulting XML document in the <code>String</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws TransformerException
     */
    public static String transformToString(final Source xsltTemplate,
            final Source document, final Map<String, Object> parameters,
            final XMLUtilities xmlUtilities)
            throws XPathFactoryConfigurationException,
            ParserConfigurationException, TransformerException {
        if (xmlUtilities != null) {
            return xmlUtilities.transformToString(xsltTemplate, document,
                    parameters);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.transformToString(xsltTemplate, document,
                parameters);
    }
    
    /**
     * transforms specified XML document using XSLT (compiled) template
     * 
     * @param xsltTemplate
     *            template to use
     * @param document
     *            XML document to transform
     * @param parameters
     *            parameters for the transformation
     * @param xmlUtilities
     *            custom <code>XMLUtilities</code> to use
     * 
     * @return resulting XML document in the <code>String</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws TransformerException
     */
    public static String transformToString(final Templates xsltTemplate,
            final Source document, final Map<String, Object> parameters,
            final XMLUtilities xmlUtilities)
            throws XPathFactoryConfigurationException,
            ParserConfigurationException, TransformerException {
        if (xmlUtilities != null) {
            return xmlUtilities.transformToString(xsltTemplate, document,
                    parameters);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.transformToString(xsltTemplate, document,
                parameters);
    }
    
    /**
     * transforms specified XML document using XSLT (compiled) template
     * 
     * @param xsltTemplate
     *            template to use
     * @param document
     *            XML document to transform
     * @param parameters
     *            parameters for the transformation
     * 
     * @return resulting XML document in the <code>String</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws TransformerException
     */
    public static String transformToString(final Templates xsltTemplate,
            final Source document, final Map<String, Object> parameters)
            throws XPathFactoryConfigurationException,
            ParserConfigurationException, TransformerException {
        return transformToString(xsltTemplate, document, parameters,
                XMLTools.INTERNAL_XMLUTILITIES);
    }
    
    /**
     * transforms specified XML document using XSLT (compiled) template
     * 
     * @param xsltTemplate
     *            template to use
     * @param document
     *            XML document to transform
     * @param xmlUtilities
     *            custom <code>XMLUtilities</code> to use
     * 
     * @return resulting XML in the <code>String</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws TransformerException
     */
    public static String transformToString(final Templates xsltTemplate,
            final Source document, final XMLUtilities xmlUtilities)
            throws XPathFactoryConfigurationException,
            ParserConfigurationException, TransformerException {
        return transformToString(xsltTemplate, document, null, xmlUtilities);
    }
    
    /**
     * transforms specified XML document using XSLT (compiled) template
     * 
     * @param xsltTemplate
     *            template to use
     * @param document
     *            XML document to transform
     * 
     * @return resulting XML in the <code>String</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws TransformerException
     */
    public static String transformToString(final Templates xsltTemplate,
            final Source document) throws XPathFactoryConfigurationException,
            ParserConfigurationException, TransformerException {
        return transformToString(xsltTemplate, document, null,
                XMLTools.INTERNAL_XMLUTILITIES);
    }
    
    /**
     * transforms specified XML document using XSLT (compiled) template
     * 
     * @param xsltTemplate
     *            template to use
     * @param document
     *            XML document to transform
     * @param parameters
     *            parameters for the transformation
     * @param xmlUtilities
     *            custom <code>XMLUtilities</code> to use
     * 
     * @return resulting XML in the <code>Document</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     * @throws TransformerException
     */
    public static Document transformToDocument(final Templates xsltTemplate,
            final Source document, final Map<String, Object> parameters,
            final XMLUtilities xmlUtilities)
            throws XPathFactoryConfigurationException,
            ParserConfigurationException, SAXException, IOException,
            TransformerException {
        if (xmlUtilities != null) {
            return xmlUtilities.transformToDocument(xsltTemplate, document,
                    parameters);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.transformToDocument(xsltTemplate,
                document, parameters);
    }
    
    /**
     * transforms specified XML document using XSLT (compiled) template
     * 
     * @param xsltTemplate
     *            template to use
     * @param document
     *            XML document to transform
     * @param parameters
     *            parameters for the transformation
     * 
     * @return resulting XML in the <code>Document</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     * @throws TransformerException
     */
    public static Document transformToDocument(final Templates xsltTemplate,
            final Source document, final Map<String, Object> parameters)
            throws XPathFactoryConfigurationException,
            ParserConfigurationException, SAXException, IOException,
            TransformerException {
        return transformToDocument(xsltTemplate, document, parameters,
                XMLTools.INTERNAL_XMLUTILITIES);
    }
    
    /**
     * transforms specified XML document using XSLT (compiled) template
     * 
     * @param xsltTemplate
     *            template to use
     * @param document
     *            XML document to transform
     * @param xmlUtilities
     *            custom <code>XMLUtilities</code> to use
     * 
     * @return resulting XML in the <code>Document</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     * @throws TransformerException
     */
    public static Document transformToDocument(final Templates xsltTemplate,
            final Source document, final XMLUtilities xmlUtilities)
            throws XPathFactoryConfigurationException,
            ParserConfigurationException, SAXException, IOException,
            TransformerException {
        return transformToDocument(xsltTemplate, document, null, xmlUtilities);
    }
    
    /**
     * transforms specified XML document using XSLT (compiled) template
     * 
     * @param xsltTemplate
     *            template to use
     * @param document
     *            XML document to transform
     * 
     * @return resulting XML in the <code>Document</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     * @throws TransformerException
     */
    public static Document transformToDocument(final Templates xsltTemplate,
            final Source document) throws XPathFactoryConfigurationException,
            ParserConfigurationException, SAXException, IOException,
            TransformerException {
        return transformToDocument(xsltTemplate, document, null,
                XMLTools.INTERNAL_XMLUTILITIES);
    }
    
    /**
     * loads document from <code>String</code> into the <code>Document</code>
     * 
     * @param source
     *            source XML
     * 
     * @return resulting XML
     * 
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    public static Document loadDocumentFromString(final String source)
            throws TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException,
            SAXException, IOException {
        return loadDocumentFromString(source, INTERNAL_XMLUTILITIES);
    }
    
    /**
     * loads document from <code>String</code> into the <code>Document</code>
     * 
     * @param source
     *            source XML
     * @param xmlUtilities
     *            custom <code>XMLUtilities</code> to use
     * 
     * @return resulting XML
     * 
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    public static Document loadDocumentFromString(final String source,
            final XMLUtilities xmlUtilities)
            throws TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException,
            SAXException, IOException {
        XMLUtilities xmlUtils;
        if (xmlUtilities != null) {
            xmlUtils = xmlUtilities;
        } else {
            if (XMLTools.xmlUtilities == null) {
                initializeXMLUtilities();
            }
            
            xmlUtils = XMLTools.xmlUtilities;
        }
        
        return loadDocumentFromString(source, xmlUtils.getDocumentBuilder());
    }
    
    /**
     * loads document from <code>String</code> into the <code>Document</code>
     * 
     * @param source
     *            source XML
     * @param documentBuilder
     *            custom document builder
     * 
     * @return resulting XML
     * 
     * @throws SAXException
     * @throws IOException
     */
    public static Document loadDocumentFromString(final String source,
            final DocumentBuilder documentBuilder) throws SAXException,
            IOException {
        final StringReader sr = new StringReader(source);
        final BufferedReader br = new BufferedReader(sr);
        final InputSource is = new InputSource(br);
        
        final Document result = documentBuilder.parse(is);
        
        br.close();
        sr.close();
        
        return result;
    }
    
    /**
     * loads document from <code>String</code> into the <code>Document</code>
     * 
     * @param source
     *            source XML
     * @param documentBuilder
     *            cutom DocumentBuilder to use
     * @param xmlUtilities
     *            custom <code>XMLUtilities</code> to use
     * 
     * @return resulting XML
     * 
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    public static Document loadDocumentFromString(final String source,
            final DocumentBuilder documentBuilder,
            final XMLUtilities xmlUtilities)
            throws TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException,
            SAXException, IOException {
        return loadDocumentFromString(source, xmlUtilities);
    }
    
    /**
     * converts XML Source into String
     * 
     * @param source
     *            source Document
     * 
     * @return XML in the String
     * 
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws TransformerException
     */
    public static String sourceToString(final Source source)
            throws TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException,
            IOException, TransformerException {
        return sourceToString(source, XMLTools.INTERNAL_XMLUTILITIES);
    }
    
    /**
     * converts XML Source into String
     * 
     * @param source
     *            source Document
     * @param xmlUtilities
     *            <code>XMLUtilities</code> to use
     * 
     * @return XML in the String
     * 
     * @throws TransformerConfigurationException
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws TransformerException
     */
    public static String sourceToString(final Source source,
            final XMLUtilities xmlUtilities)
            throws TransformerConfigurationException,
            XPathFactoryConfigurationException, ParserConfigurationException,
            IOException, TransformerException {
        if (xmlUtilities != null) {
            return xmlUtilities.sourceToString(source);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.sourceToString(source);
    }
    
    /**
     * transforms specified XML using specified XSLT template
     * 
     * @param xsltTemplate
     *            XSLT template
     * @param document
     *            source XML document
     * @param parameters
     *            parameters for the template
     * @param xmlUtilities
     *            <code>XMLUtilities</code> to use
     * @return resulting XML in the <code>Document</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     * @throws TransformerException
     */
    public static Document transformToDocument(final Source xsltTemplate,
            final Source document, final Map<String, Object> parameters,
            final XMLUtilities xmlUtilities)
            throws XPathFactoryConfigurationException,
            ParserConfigurationException, SAXException, IOException,
            TransformerException {
        if (xmlUtilities != null) {
            return xmlUtilities.transformToDocument(xsltTemplate, document,
                    parameters);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities.transformToDocument(xsltTemplate,
                document, parameters);
    }
    
    /**
     * transforms specified XML using specified XSLT template
     * 
     * @param xsltTemplate
     *            XSLT template
     * @param document
     *            source XML document
     * @param parameters
     *            parameters for the template
     * @return resulting XML in the <code>Document</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     * @throws TransformerException
     */
    public static Document transformToDocument(final Source xsltTemplate,
            final Source document, final Map<String, Object> parameters)
            throws XPathFactoryConfigurationException,
            ParserConfigurationException, SAXException, IOException,
            TransformerException {
        return transformToDocument(xsltTemplate, document, parameters,
                INTERNAL_XMLUTILITIES);
    }
    
    /**
     * transforms specified XML using specified XSLT template
     * 
     * @param xsltTemplate
     *            XSLT template
     * @param document
     *            source XML document
     * @param xmlUtilities
     *            <code>XMLUtilities</code> to use
     * @return resulting XML in the <code>Document</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     * @throws TransformerException
     */
    public static Document transformToDocument(final Source xsltTemplate,
            final Source document, final XMLUtilities xmlUtilities)
            throws XPathFactoryConfigurationException,
            ParserConfigurationException, SAXException, IOException,
            TransformerException {
        if (xmlUtilities != null) {
            return xmlUtilities.transformToDocument(xsltTemplate, document);
        }
        
        if (XMLTools.xmlUtilities == null) {
            initializeXMLUtilities();
        }
        
        return XMLTools.xmlUtilities
                .transformToDocument(xsltTemplate, document);
    }
    
    /**
     * transforms specified XML using specified XSLT template
     * 
     * @param xsltTemplate
     *            XSLT template
     * @param document
     *            source XML document
     * @return resulting XML in the <code>Document</code>
     * 
     * @throws XPathFactoryConfigurationException
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     * @throws TransformerException
     */
    public static Document transformToDocument(final Source xsltTemplate,
            final Source document) throws XPathFactoryConfigurationException,
            ParserConfigurationException, SAXException, IOException,
            TransformerException {
        return transformToDocument(xsltTemplate, document,
                INTERNAL_XMLUTILITIES);
    }
    
    /**
     * loads XML from String
     * 
     * @param source
     *            source string
     * 
     * @return XML in the <code>Source</code>
     */
    public static Source loadSourceFromString(final String source) {
        return new StreamSource(new StringReader(source));
    }
    
    /**
     * loads XML from String
     * 
     * @param source
     *            source string
     * @param systemId
     *            system ID
     * 
     * @return XML in the <code>Source</code>
     */
    public static Source loadSourceFromString(final String source,
            final String systemId) {
        return new StreamSource(new StringReader(source), systemId);
    }
    
}
